package me.zhenqu.redis;

import redis.clients.jedis.Jedis;

import java.lang.ref.WeakReference;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

public class PooledJedis extends Jedis {
    private static BlockingQueue<WeakReference<PooledJedis>> all = new LinkedBlockingQueue<WeakReference<PooledJedis>>();

    static {
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    while (all.size() > 50) {
                        try {
                            WeakReference<PooledJedis> taken = all.take();
                            PooledJedis jedis = taken.get();
                            if (jedis != null) {
                                if (jedis.test()) {
                                    all.offer(taken);
                                }
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                        Thread.yield();
                    }
                    try {
                        Thread.sleep(5 * 60 * 1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        t.setDaemon(true);
        t.setName("Jedis-resource-cleaner");
        t.start();
    }

    private String key;


    public PooledJedis(String host, int port) {
        super(host, port);
        key = host + ":" + port;
        all.offer(new WeakReference<PooledJedis>(this));
    }

    public String getKey() {
        return key;
    }

    @Override
    public String toString() {
        return key;
    }

    @Override
    public String ping() {
        if (invalid) return null;
        return super.ping();
    }

    private boolean idle;
    private long lastTime = System.currentTimeMillis();
    private boolean invalid;

    public boolean isIdle() {
        return idle;
    }

    public void setIdle(boolean idle) {
        lastTime = System.currentTimeMillis();
        this.idle = idle;
    }


    public boolean test() {
        if (System.currentTimeMillis() - lastTime > 60 * 30 * 1000) {
//            System.err.println("Close timeout connection to " + key);
            try {
                quit();
            } catch (Exception ignored) {

            }
            try {
                disconnect();
            } catch (Exception ignored) {

            }
            invalid = true;
        }
        return !invalid && isConnected();
    }

    public boolean isValid() {
        return !invalid;
    }
}
